#!/usr/bin/env rdmd

import
	tango.io.device.Array,
	tango.stdc.stringz,
	tango.io.Stdout ,
	
	tango.math.random.Random,
	tango.net.device.Berkeley,
	tango.net.InternetAddress,
	tango.net.InternetAddress,
	Int	= tango.text.convert.Integer ,
	tango.core.Array ,
	tango.io.device.Array ,
	tango.io.device.File ,
	libeventd.Types ;


struct _Struct {
	struct _Field {
		int		_index ;
		int		_size	;
		int		_offset ;
		char[]	_name ;
	}
	char[]	_name ;
	int		_size	;
	int		_len	;
	_Field*[]	_fields ;
	char[]	_typeid ;
	
	static _Struct*[]	 list ;
	
	static void Load(alias S)(char[][] _exclude = null){
		_Struct* p	= new _Struct ;
		p._name	= S.stringof ;
		p._size	= S.sizeof ;
		p._typeid	= typeid(S).toString ;
		int	idx	= 0 ;
		S	_s ;
		foreach(int i, c ; _s.tupleof ) {
			_Field* _p	= new _Field ;
			_p._name	= S.tupleof[i].stringof[ S.stringof.length + 3 ..$] ;
			bool	v	= true ;
			if( _p._name.length > 2 && _p._name[0] is '_' && _p._name[1] is '_' ){
				v	= false ;
			}else if( _exclude !is null ) {
				if( contains( _exclude , _p._name) ){
					v	= false ;
				}
			}
			_p._size	= c.sizeof ;
			_p._offset	= S.tupleof[i]. offsetof ;
			_p._index	=  v ? idx++ : -1 ;
			p._fields	~= _p ;
		}
		p._len	= idx ;
		list		~= p	;
	}
	
	static void Dump(){
		foreach( s ; list ){
			Stdout.formatln("{}	{}", s._name, s._size );
			foreach( f; s._fields ){
				Stdout.formatln("	{}	{}	{}	{}",	f._name, f._offset, f._size, f._index );
			}
		}
	}
	
	static void GenTest(){
		auto bu	= new Array(1024, 1024) ;
		auto b2	= new Array(1024, 1024) ;
		bu( File.get(`header.txt`) ) ;
		bu( File.get(`struct_start.txt`) ) ;
		int	_len1	= bu.slice.length ;
		bu("\n");
		b2("void _d_struct_dump(){\n\t_D_field*	fptr ;\n\tint i = 0 ;\n");
		int	_len	= 0 ;
		foreach( s ; list ){
			_len++;
			GenStructTest(s, bu, b2);
		}
		space( bu );
		space( b2 );
		bu("};\n");
		bu("\nint _struct_len = ")( Int.toString(_len) ) (" ;\n");
		b2("\n}\n");
		
		bu( b2.slice );
		
		int	_len2	= bu.slice.length ;
		bu( File.get(`struct_end.txt`) )("\n");
		File.set(`../../test.c`, bu.slice );
		
		return ;
		char[] _da	= cast(char[]) bu.slice  ;
		_da[_len2]	= 0 ;
		printf("%s", &_da[_len1]);
	}
	
	static void GenStructTest(_Struct* s, Array bu, Array b2){
		bu("\t{\"")(s._name)("\", ")( Int.toString(s._size) )(", sizeof(struct ")(s._name)("), ")( Int.toString(s._len ) ) ;
		
		if( s._len > 0 ){
			b2("\t// ")( s._name )("	(")(s._typeid)(") ;\n");
			b2("\t_struct_list[i].ptr	=  	malloc( sizeof(_D_field) * ")( Int.toString(s._len) )(" ) ;\n");
			int	i	= 0 ;
			foreach( f ; s._fields ) if( f._index>= 0 ) {
				b2("\t\t// ")( Int.toString(i) )(": ")( f._name )(";\n");
				scope(exit) {
					b2("\n");
					i++;
				}
				if( i is 0 ){
					b2("\t\tfptr	= _struct_list[i].ptr ;\n");
				}else{
					b2("\t\tfptr++ ;\n");
				}
				
				b2("\t\tfptr->name	= \"")( f._name )("\" ;\n");
				b2("\t\tfptr->_off	= ")( Int.toString(f._offset) )(" ;\n");
				b2("\t\tfptr->_size	= ")( Int.toString(f._size) )(" ;\n");
				b2("\t\tfptr->off		= offsetof(struct ")(s._name)(", ")(f._name)(") ;\n");
				b2("\t\tfptr->size		= FSIZ(struct ")(s._name)(", ")(f._name)(") ;\n");
			}
			b2("\ti++;\n");
		}
		bu("},\n");
	}
	
	static void space(Array bu){
		if( bu is null ||  bu.slice .length is 0 ) return ;
		char* _p	= cast(char*) &( bu.slice )[ 0 ] ;
		char* p	= cast(char*) &( bu.slice )[ $ - 1 ] ;
		
		while(  p > _p ){
			if( *p is '\n' || *p is '\r' || *p is '\t' || *p is ' ' ){
				p-- ;
			}else{
				break ;
			}
		}
		
		if( *p is ',' ){
			*p	= ' ' ;
		}
		
	}
}

void struct_dump() {
	
	_Struct.Load!(ev_token_bucket)();
	_Struct.Load!(ev_token_bucket_cfg)();
	
	_Struct.Load!(bufferevent_private)();
	_Struct.Load!(bufferevent_rate_limit_group)();
	_Struct.Load!(bufferevent_rate_limit)();
	_Struct.Load!(bufferevent_ops)();
	//_Struct.Load!(bufferevent_async)();
	
	_Struct.Load!(rlim_group_member_list)();
	
	_Struct.Load!(evsig_info)();
	
	_Struct.Load!(event)(["ev_next_with_common_timeout", "min_heap_idx", "ev_signal", "ev_io"]);
	_Struct.Load!(eventop)();

	_Struct.Load!(event_signal_map)();
	_Struct.Load!(common_timeout_list)();
	_Struct.Load!(event_changelist)();
	_Struct.Load!(event_base)();

	_Struct.Load!(event_config_entry)();
	_Struct.Load!(event_configq)();
	_Struct.Load!(event_config)();
	
	_Struct.Load!(deferred_cb)(["queued"]);
	_Struct.Load!(deferred_cb_queue)(["queued"]);
	
	_Struct.Load!(event_change)();
	
	_Struct.Load!(evbuffer)();
	_Struct.Load!(evbuffer_cb_entry)(["cb_func", "cb_obsolete"]);
	_Struct.Load!(evbuffer_chain)();
	_Struct.Load!(evbuffer_chain_fd)();
	_Struct.Load!(evbuffer_chain_reference)();
	_Struct.Load!(bufferevent_ops)();
	
	_Struct.Load!(bufferevent)();
	_Struct.Load!(evkeyval)();
	
	_Struct.Load!(event_iocp_port)();
	_Struct.Load!(event_overlapped)();
	_Struct.Load!(event_iocp_port)();
	
	_Struct.Load!(sockaddr_in6)();
	_Struct.Load!(sockaddr_storage)();
	
	
	_Struct.Load!(evhttp)();
	_Struct.Load!(evhttp_bound_socket)();
	_Struct.Load!(evhttp_cb)();
	_Struct.Load!(evhttp_connection)();
	_Struct.Load!(evhttp_request)();
	
	//_Struct.Load!(request)();
	_Struct.Load!(evdns_server_request)();
	_Struct.Load!(evdns_server_question)();

	_Struct.Load!(evrpc_status)();
	_Struct.Load!(evrpc)();
	
	_Struct.Load!(evthread_lock_callbacks)();
	
	
	
	//_Struct.Load!(evconnlistener)();
	
	_Struct.Dump ;
	_Struct.GenTest ;
}





void main() {
	struct_dump;
}





